

local Block = import("./Block.lua");
local ShadowBlock = commonlib.inherit(Block);

function ShadowBlock:ctor()
    self.__shadow_block_width_unit_count__, self.__shadow_block_height_unit_count__ = 16, 12;
end

function ShadowBlock:Init(blockly)
    ShadowBlock._super.Init(self, blockly, {
        type = "__shadow_block__",
        previousStatement = true,
        nextStatement = true,
        output = true,
        color = 0x00000080,
        isDraggable = false,
        message = "",
        arg = {},
    });

    self:SetLeftTopUnitCount(0, 0);
    self:SetWidthHeightUnitCount(self.__shadow_block_width_unit_count__, self.__shadow_block_height_unit_count__);

    self.__shadow_next_connection__ = self.__next_connection__;
    self.__shadow_previous_connection__ = self.__previous_connection__;
    self.__shadow_output_connection__ = self.__output_connection__;
    self.__shadow_block__ = nil;
    self.__is_shadow_block__ = true;

    return self;
end

function ShadowBlock:Shadow(block)
    self:Disconnection();
    self.__shadow_block__ = block;
    if (not block) then return self:GetBlockly():RemoveBlock(self) end

    if (block.__next_connection__) then
        local lastNextBlock = block:GetLastNextBlock();
        self.__next_connection__ = self.__shadow_next_connection__;
        self.__next_connection__:SetCheck(lastNextBlock.__next_connection__:GetCheck());
        self.__next_connection__:SetLeftTopUnitCount(lastNextBlock.__next_connection__:GetLeftTopUnitCount());
    else
        self.__next_connection__ = nil;
    end
    if (block.__previous_connection__) then
        self.__previous_connection__ = self.__shadow_previous_connection__;
        self.__previous_connection__:SetCheck(block.__previous_connection__:GetCheck());
        self.__previous_connection__:SetLeftTopUnitCount(block.__previous_connection__:GetLeftTopUnitCount());
    else
        self.__previous_connection__ = nil;
    end
    if (block.__output_connection__) then
        self.__output_connection__ = self.__shadow_output_connection__;
        self.__output_connection__:SetCheck(block.__output_connection__:GetCheck());
        self.__output_connection__:SetLeftTopUnitCount(block.__output_connection__:GetLeftTopUnitCount());
    else
        self.__output_connection__ = nil;
    end
    self:SetLeftTopUnitCount(block:GetLeftTopUnitCount());
    self:SetWidthHeightUnitCount(block:GetWidthHeightUnitCount());
    self:SetMaxWidthHeightUnitCount(block:GetMaxWidthHeightUnitCount());
    self:SetTotalWidthHeightUnitCount(block:GetTotalWidthHeightUnitCount());
    self:TryConnectionBlock();
end

function ShadowBlock:GetShadowWidthHeightUnitCount()
    return self.__shadow_block_width_unit_count__, self.__shadow_block_height_unit_count__;
end

function ShadowBlock:UpdateWidthHeightUnitCount()
    local widthUnitCount, heightUnitCount = self:GetShadowWidthHeightUnitCount();
    local maxWidthUnitCount, maxHeightUnitCount = widthUnitCount, heightUnitCount;

    self:SetWidthHeightUnitCount(widthUnitCount, heightUnitCount);
    self:SetMaxWidthHeightUnitCount(maxWidthUnitCount, maxHeightUnitCount);

    local nextBlock = self:GetNextBlock();
    if (nextBlock) then 
        local _, _, _, _, nextBlockTotalWidthUnitCount, nextBlockTotalHeightUnitCount = nextBlock:UpdateWidthHeightUnitCount();
        self:SetTotalWidthHeightUnitCount(math.max(maxWidthUnitCount, nextBlockTotalWidthUnitCount), maxHeightUnitCount + nextBlockTotalHeightUnitCount);
    else
        self:SetTotalWidthHeightUnitCount(maxWidthUnitCount, maxHeightUnitCount);
    end
    local totalWidthUnitCount, totalHeightUnitCount = self:GetTotalWidthHeightUnitCount();
    return maxWidthUnitCount, maxHeightUnitCount, widthUnitCount, heightUnitCount, totalWidthUnitCount, totalHeightUnitCount;
end

function ShadowBlock:ConnectionBlock(block)
    if (self.__shadow_block__ == block) then return end 
    return ShadowBlock._super.ConnectionBlock(self, block);
end

function ShadowBlock:Render()
    if (not self.__previous_connection__ and not self.__next_connection__ or not self.__shadow_block__) then return end
    if ((self.__previous_connection__ and self.__previous_connection__:IsConnection()) or (self.__next_connection__ and self.__next_connection__:IsConnection())) then 
        local leftUnitCount, topUnitCount = self:GetLeftTopUnitCount();
        local widthUnitCount, heightUnitCount = self.__shadow_block__:GetWidthHeightUnitCount();
        self:SetBrushColor(self:GetColor());
        self:DrawShadowStatementBlock(widthUnitCount, self.__shadow_block_height_unit_count__, leftUnitCount, topUnitCount);
    end 

    local nextBlock = self:GetNextBlock();
    if (nextBlock) then nextBlock:Render() end
end

return ShadowBlock;